#include <string.h>
#include <iostream>
using std::cout;
using std::endl;
using std::ostream;

class CowString
{
public:
    CowString();

    CowString(const char * pstr);

    CowString(const CowString& rhs);

    CowString& operator=(const CowString & rhs);

    ~CowString();

    int size() const{ return strlen(_pstr); }
    const char * c_str() const{ return _pstr; }

    //获取引用计数
    int use_count(){ 
        return *(int*)(_pstr - kRefcountLength);
    }

    friend
    ostream & operator<<(ostream & os, const CowString & rhs);
private:
    void initRefcount(){
        *(int*)(_pstr - kRefcountLength) = 1;
    }

    void increaseRefcount(){
        ++*(int*)(_pstr - kRefcountLength);
    }

    void decreaseRefcount(){
        --*(int*)(_pstr - kRefcountLength);
    }

    static const int kRefcountLength = 4;
    char * _pstr;
};

ostream & operator<<(ostream & os, const CowString & rhs){
    os << rhs._pstr;
    return os;
}

CowString::CowString()
: _pstr(new char[1 + kRefcountLength]() + kRefcountLength)
{
    cout << "CowString()" << endl;
    initRefcount();
}

CowString::~CowString(){
    decreaseRefcount();
    if(use_count() == 0){
        delete [] (_pstr - kRefcountLength);
        _pstr = nullptr;
        cout << " >> delete heap " << endl;
    }
}

CowString::CowString(const CowString & rhs)
: _pstr(rhs._pstr)
{
    increaseRefcount();
    cout << "CowString(const CowString &)" << endl;
}


void test0(){
    CowString str1;
    CowString str2 = str1;
    cout << "str1:" << str1 << endl;
    cout << "str2:" << str2 << endl;
    cout << str1.use_count() << endl;
    cout << str2.use_count() << endl;
}

int main(void){
    test0();
    return 0;
}
